#include <stdio.h>
#include "../include/mergeToVx.h"/*winie*/
#include "../include/target_defines.h"
#include "../include/wtapi_type.h"
#include "../include/wtapi_lowlevel.h"

#include "../include/wt_dm642.h"
#include "../include/host_cmd.h"
#define DM642_GBLCTL	((0x01800000-0x01800000)/4)
#define DM642_CECTL1	((0x01800004-0x01800000)/4)
#define DM642_CECTL0	((0x01800008-0x01800000)/4)
#define DM642_CECTL2	((0x01800010-0x01800000)/4)
#define DM642_CECTL3	((0x01800014-0x01800000)/4)
#define DM642_SDCTL		((0x01800018-0x01800000)/4)
#define DM642_SDTIM		((0x0180001C-0x01800000)/4)
#define DM642_SDEXT		((0x01800020-0x01800000)/4)
#define DM642_PDTCTL	((0x01800040-0x01800000)/4)
#define DM642_CESEC1	((0x01800044-0x01800000)/4)
#define DM642_CESEC0	((0x01800048-0x01800000)/4)
#define DM642_CESEC2	((0x01800050-0x01800000)/4)
#define DM642_CESEC3	((0x01800054-0x01800000)/4)

#define DM642_RSTSRC	((0x01C00000-0x01800000)/4)
#define DM642_PCIIS		((0x01C00008-0x01800000)/4)
#define DM642_PCIIEN	((0x01C0000C-0x01800000)/4)
#define DM642_DSPMA		((0x01C00010-0x01800000)/4)
#define DM642_PCIMA		((0x01C00014-0x01800000)/4)
#define DM642_PCIMC		((0x01C00018-0x01800000)/4)
#define DM642_CDSPA		((0x01C0001C-0x01800000)/4)
#define DM642_CPCIA		((0x01C00020-0x01800000)/4)
#define DM642_CCNT		((0x01C00024-0x01800000)/4)
#define DM642_HSR		((0x01C1FFF0-0x01800000)/4)
#define DM642_HDCR		((0x01C1FFF4-0x01800000)/4)
#define DM642_DSPP		((0x01C1FFF8-0x01800000)/4)
#define DM642_EEADD		((0x01C20000-0x01800000)/4)
#define DM642_EEDAT		((0x01C20004-0x01800000)/4)
#define DM642_EECTL		((0x01C20008-0x01800000)/4)
#define DM642_PCI_TRCTL	((0x01C30000-0x01800000)/4)

#define DM642_GPEN		((0x01b00000-0x01800000)/4)
#define DM642_GPDIR		((0x01b00004-0x01800000)/4)
#define DM642_GPVAL		((0x01b00008-0x01800000)/4)

#define DM642_RCERE00	((0x018C001C-0x01800000)/4)
#define DM642_XCERE00	((0x018C0020-0x01800000)/4)

static struct WT_DSP_Host_Cmd *pHostCmd[nMaxDevice];


extern PCHAR Wtdriver_GetMapAddress(UINT32 device,UINT32 PCI_BAR);

static void Config_Enable_A(UINT32 device)
{
	UINT32 *ptr  = (UINT32 *)Wtdriver_GetMapAddress(device,PCI_BAR1);
	//GPEN Register
	ptr[DM642_GPEN]  = 0xffff; 
	
	//GPDIR Register
	//Set GP07,GP06,GP03 as output pins 
	ptr[DM642_GPDIR] = 0x00c8 ;
	
	ptr[DM642_GPVAL]=0x80;
}
static void Config_Disable_A(UINT32 device)
{
	UINT32 *ptr  = (UINT32 *)Wtdriver_GetMapAddress(device,PCI_BAR1);
	//GPEN Register
	ptr[DM642_GPEN] = 0xffff; 
	
	//GPDIR Register
	//Set GP07,GP06,GP03 as output pins 
	ptr[DM642_GPDIR] = 0x00c8 ;
	
	ptr[DM642_GPVAL]=0x00;
	
}
static void Config_Out_Low_A(UINT32 device)
{
	volatile UINT32 *ptr  = (UINT32 *)Wtdriver_GetMapAddress(device,PCI_BAR1);
	ptr[DM642_GPVAL]=0x80;
	ptr[DM642_GPVAL]=0xC0;
	ptr[DM642_GPVAL]=0x80;
}
static void Config_Out_High_A(UINT32 device)
{
	volatile UINT32 *ptr  = (UINT32 *)Wtdriver_GetMapAddress(device,PCI_BAR1);
	ptr[DM642_GPVAL]=0x88;
	ptr[DM642_GPVAL]=0xC8;
	ptr[DM642_GPVAL]=0x88;
	
}
/*
 * read FPGA config file into FPGA
 */
 UINT32 WT_DM642_FPGA_Config_A(UINT32 device, const char * rbf_filename)
{
	UINT32 filesize;
	char c;
	PCHAR data;
	UINT32 i=0;
	UINT32 j=0;
	/*int fd;
	fd=open("vxw:1.rbf",O_RDWR,0);*/
	FILE *fp=fopen(rbf_filename,"rb");
	if(fp)
	{
#if 1
		fseek(fp,0,SEEK_END);
		filesize=ftell(fp);
		data=(PCHAR)malloc(filesize);
		fseek(fp,0,SEEK_SET);
		fread(data,1,filesize,fp);
		fclose(fp);
#endif
		
		/*while(read(fd,data,1))
		{*/

		Config_Disable_A(device);		
		Config_Enable_A(device);	    
		for(i=0;i<filesize;i++)
		{
			char c=*(data+i);
			for( j=0;j<8;j++)
			{
				if((c&0x01)==0x00) 
				{
					Config_Out_Low_A(device);
				}
				else
				{
					Config_Out_High_A(device);
				}
				c=(c>>1);
			}
		}
		for(i=0;i<50;i++)
		{
			Config_Out_Low_A(device);
		}
		
		taskDelay(100);
		
		free(data);	
		
		return OK;
	}
	
	
	else return ERROR;
}
/*
 * read registers from eeprom , 'addr' is the offset of register.
 */
void WT_DM642_Read_EEPROM(UINT32 device,UINT32 addr,USHORT *data)
{
	UINT32 rv;
	UINT32 *ptr  = (UINT32 *)Wtdriver_GetMapAddress(device,PCI_BAR1);	
	//READ
	rv= addr;
	ptr[DM642_EEADD]=rv;
	rv = 0x02;
	ptr[DM642_EECTL]=rv;
	taskDelay(10);
	rv =ptr[DM642_EEDAT];
	*data = (USHORT)(rv&0xffff);
	
}
static void  WT_DM642_MapToRAM(UINT32 device)
{
	UINT32 *ptr  = (UINT32 *)Wtdriver_GetMapAddress(device,PCI_BAR1);
	ptr[DM642_DSPP] = DM642_RAM/0x400000;
}
static UINT32 WT_DM642_Load_Program(UINT32 device,PCHAR prog_file)
{

	FILE *fp1=fopen(prog_file,"rb");
	UINT32 *ptr ,i = 0;
	PCHAR ptr0;
	if(fp1)
	{
		PCHAR rom1 = (PCHAR)malloc(4*65536);
		
		fread(rom1,65536,4,fp1);

		fclose(fp1);
		
		ptr  = (UINT32 *)Wtdriver_GetMapAddress(device,PCI_BAR1);
		printf("PCI BAR1 ADDR = 0x%X!\n", ptr);
		ptr0 = Wtdriver_GetMapAddress(device,PCI_BAR0);
		printf("PCI BAR0 ADDR = 0x%X!\n", ptr0);
		WT_DM642_MapToRAM(device);
		printf("WT_DM642_MapToRAM OVER\n");
		for(i = 0; i < 4; i++)
		{
			memcpy(ptr0 + i * 65536, rom1 + i * 65536, 65536);
			printf("memcpy to ptr0 %d\n", i);
		}
		
		ptr[DM642_HDCR]=0x02;

		taskDelay(100);

		free(rom1);
		
		return OK;
	}
	
else return WT_UNSUCCESS;

}

UINT32 WT_DM642_Init(UINT32 device,UINT32 sdram_test,UINT32 sram_test,PCHAR prog_file,PCHAR rbf_file_a,PCHAR rbf_file_b)
{

	UINT32 rst=WT_SUCCESS;
#if 1
	UINT32 *ptr  = (UINT32 *)Wtdriver_GetMapAddress(device,PCI_BAR1);
	ptr[DM642_XCERE00] = 0;
	if((ptr[DM642_XCERE00]!=0x57540642))
	{
		ptr[DM642_HDCR]=0x01;
		ptr[DM642_RSTSRC]=0x10;
		ptr[DM642_HSR]=0x00; 

		ptr[DM642_GBLCTL] = DM642_GBLCTL_VALUE;
		ptr[DM642_CECTL0] = DM642_CECTL0_VALUE;
		ptr[DM642_CECTL1] = DM642_CECTL1_VALUE;
		ptr[DM642_CECTL2] = DM642_CECTL2_VALUE;
		ptr[DM642_CECTL3] = DM642_CECTL3_VALUE;
		ptr[DM642_SDCTL]  = DM642_SDCTL_VALUE;
		ptr[DM642_SDTIM]  = DM642_SDTIM_VALUE;
		
		if(WT_DM642_Load_Program(device,prog_file)!=WT_SUCCESS)
		{
			rst=WT_UNSUCCESS;
		}
		else
		{

			UINT32 offset;

			offset = ptr[DM642_RCERE00];
			
			ptr[DM642_DSPP] = offset/0x400000;

			pHostCmd[device] = (struct WT_DSP_Host_Cmd *)(Wtdriver_GetMapAddress(device,PCI_BAR0)+offset%0x400000);
			
			if(pHostCmd[device]->HostCmd_DSP_Ready!=0x57540642)
			{
				rst=WT_UNSUCCESS;
			}
			else
			{
				pHostCmd[device]->Host_Cmd_Init_Req=1;
				while(pHostCmd[device]->Host_Cmd_Init_Req){;}

			
				if(sdram_test==1)
				{
					pHostCmd[device]->SDRAM_Test_CE2_Req=1;
					while(pHostCmd[device]->SDRAM_Test_CE2_Req){;}
					if(pHostCmd[device]->SDRAM_Test_CE2==0)
					{
						rst=WT_UNSUCCESS;
					}
				}
			
				if(rst==WT_SUCCESS)
				{
					if(rbf_file_a!=NULL)
					{
						if(WT_DM642_FPGA_Config_A(device,rbf_file_a)!=WT_SUCCESS)
						{
							rst=WT_UNSUCCESS;
						}
						else
						{
						
							pHostCmd[device]->FPGA_Test_Req_A=1;
							while(pHostCmd[device]->FPGA_Test_Req_A){;}

							if(pHostCmd[device]->FP_ID_A!=0x834155aa)
							{
								rst=WT_UNSUCCESS;
							}
						}
					}					
				}
			}
		}
	}

	else
	{
		UINT32 offset;

		offset = ptr[DM642_RCERE00];
			
		ptr[DM642_DSPP] = offset/0x400000;
		rst = WT_UNSUCCESS;
		pHostCmd[device] = (struct WT_DSP_Host_Cmd *)(Wtdriver_GetMapAddress(device,PCI_BAR0)+offset%0x400000);
	
	}
	return rst;
#endif
}
void*   WT_DM642_Get_pHsotCmd(UINT32 device)
{
	return	pHostCmd[device]; 
}

UINT32 WT_DM642_ReInit(UINT32 device,UINT32 sdram_test,UINT32 sram_test,PCHAR prog_file,PCHAR rbf_file_a,PCHAR rbf_file_b)
{
	UINT32 *ptr  = (UINT32 *)Wtdriver_GetMapAddress(device,PCI_BAR1);
	ptr[DM642_XCERE00]=0;
	return WT_DM642_Init(device,sdram_test,sram_test,prog_file,rbf_file_a,rbf_file_b);
}
